// Laser.java
// Jim Sproch
// Created: March 31, 2007
// Modified: January 11, 2008
// Part of the Aforce Port
// Mac < Windows < Linux

/**
	TimeBomb explodes after a specific amount of time!
	@author Jim Sproch
	@version 0.1a beta
*/


import java.awt.*;
import javax.swing.*;
import java.util.*;

public class Laser extends JComponent implements MovableObject, Weapon
{
	Size mysize;
	Location mylocation;
	int direction;
	int myid;
	int myteam;
	Status mystatus;
	Color color = Color.ORANGE;
	long deathTime = AForce.clicker.getElapsedTime()+100;

	// Objects we already hit, so we don't double dip
	ArrayList<AbstractObject> alreadyHit = new ArrayList<AbstractObject>();

	int maxmin = 0;

	boolean real = true;

	// Because this object is Serializable because it extends JComponent
	private static final long serialVersionUID = 7526471155622776147L;

	ArrayList<Boundary> boundaries = new ArrayList<Boundary>();

	AForceEnv field;
	Ship owner;


	public String toString()
	{
		return "Laser @ " + mylocation;
	}


	public int getDirection()
	{
		return direction;
	}

	public void setReal(boolean real)
	{
		this.real = real;
	}

	public void move()
	{
		return;
	}

	Laser(Ship owner)
	{
		this.owner = owner;
		mystatus = new Status(1,90);
		this.direction = Direction.reverse(owner.getDirection());
		myteam = owner.getTeam();
	}

	Laser(Ship owner, Color color)
	{
		this(owner);
		this.color = color;
	}

	public boolean isDestroyable()
	{
		return false;
	}

	public void setlocation()
	{

		// When we set the location for a laser going NORTH or WEST, we have to check to make sure
		// there are non-destroyable-objects between the laser's location and the owner (the ship that fires the laser)


		if(owner.getDirection() == Direction.NORTH)
		{
			ArrayList<Boundary> obsticals = AForce.field.getBoundariesH(owner.getlocation().getx()+owner.getsize().getx()/2, 0, owner.getlocation().getx()+owner.getsize().getx()/2+3, owner.getlocation().gety()+owner.getsize().gety());

			maxmin = 0;
			for(int i = 0; i < obsticals.size(); i++)
			{
				if(obsticals.get(i).getOwner() instanceof Block && obsticals.get(i).gety1() > maxmin)
					maxmin = obsticals.get(i).gety1();
			}

			mylocation = new Location(owner.getlocation().getx()+owner.getsize().getx()/2, maxmin);
		}

		if(owner.getDirection() == Direction.SOUTH)
		{
			ArrayList<Boundary> obsticals = AForce.field.getBoundariesH(owner.getlocation().getx()+owner.getsize().getx()/2, owner.getlocation().gety()+owner.getsize().gety(), owner.getlocation().getx()+owner.getsize().getx()/2+3, AForce.field.getsize().gety());

			maxmin = AForce.field.getsize().gety() - owner.getlocation().gety()-owner.getsize().gety();
			for(int i = 0; i < obsticals.size(); i++)
			{
				if(obsticals.get(i).getOwner() instanceof Block && obsticals.get(i).gety1() - owner.getlocation().gety()-owner.getsize().gety() < maxmin)
				{
					maxmin = obsticals.get(i).gety1() - owner.getlocation().gety()-owner.getsize().gety();
				}
			}
			mylocation = new Location(owner.getlocation().getx()+owner.getsize().getx()/2, owner.getlocation().gety()+owner.getsize().gety());
		}

		if(owner.getDirection() == Direction.WEST)
		{
			ArrayList<Boundary> obsticals = AForce.field.getBoundariesV(0, owner.getlocation().gety()+owner.getsize().gety()/2, owner.getlocation().getx()+owner.getsize().getx()/2, owner.getlocation().gety()+owner.getsize().gety()/2+3);

			maxmin = 0;
			for(int i = 0; i < obsticals.size(); i++)
			{
				if(obsticals.get(i).getOwner() instanceof Block && obsticals.get(i).getx1() > maxmin)
					maxmin = obsticals.get(i).getx1();
			}

			mylocation = new Location(maxmin, owner.getlocation().gety()+owner.getsize().gety()/2);
		}

		if(owner.getDirection() == Direction.EAST)
		{
			ArrayList<Boundary> obsticals = AForce.field.getBoundariesV(owner.getlocation().getx()+owner.getsize().getx(), owner.getlocation().gety()+owner.getsize().gety()/2, AForce.field.getsize().gety(), owner.getlocation().gety()+owner.getsize().gety()/2+3);

			maxmin = AForce.field.getsize().getx()-owner.getlocation().getx()-owner.getsize().getx();
			for(int i = 0; i < obsticals.size(); i++)
				if(obsticals.get(i).getOwner() instanceof Block && obsticals.get(i).getx1()-owner.getlocation().getx()-owner.getsize().getx() < maxmin)
					maxmin = obsticals.get(i).getx1()-owner.getlocation().getx()-owner.getsize().getx();

			mylocation = new Location(owner.getlocation().getx()+owner.getsize().getx(), owner.getlocation().gety()+owner.getsize().gety()/2);
		}

	}

	public void setsize()
	{
		if(owner.getDirection() == Direction.NORTH) mysize = new Size(3, owner.getlocation().gety()-mylocation.gety());
		if(owner.getDirection() == Direction.SOUTH) mysize = new Size(3, maxmin);
		if(owner.getDirection() == Direction.WEST) mysize = new Size(owner.getlocation().getx()-mylocation.getx(), 3);
		if(owner.getDirection() == Direction.EAST) mysize = new Size(maxmin, 3);
	}


	public void dodamage()
	{
		ArrayList<AbstractObject> obsticals = inRange();

		for(int i = 0; i < obsticals.size(); i++)
		{
			Status.collision(this, obsticals.get(i));
		}

		alreadyHit.addAll(obsticals);
	}

	public void hit(AbstractObject badguy)
	{
		if(alreadyHit.contains(badguy)) return;
		alreadyHit.add(badguy);
		badguy.getStatus().setHealth(0);
	}


	public ArrayList<AbstractObject> inRange()
	{
		ArrayList<Boundary> obsticals = null;
		ArrayList<AbstractObject> output = new ArrayList<AbstractObject>();

		if(owner.getDirection() == Direction.NORTH)
		{
			obsticals = AForce.getField().getBoundariesH(mylocation.getx(), mylocation.gety(), mylocation.getx()+mysize.getx(), mylocation.gety()+mysize.gety());
		}

		if(owner.getDirection() == Direction.SOUTH)
		{
			obsticals = AForce.getField().getBoundariesH(mylocation.getx(), mylocation.gety(), mylocation.getx()+mysize.getx(), mylocation.gety()+mysize.gety());
		}

		if(owner.getDirection() == Direction.WEST)
		{
			obsticals = AForce.getField().getBoundariesV(mylocation.getx(), mylocation.gety(), mylocation.getx()+mysize.getx(), mylocation.gety()+mysize.gety());
		}

		if(owner.getDirection() == Direction.EAST)
		{
			obsticals = AForce.getField().getBoundariesV(mylocation.getx(), mylocation.gety(), mylocation.getx()+mysize.getx(), mylocation.gety()+mysize.gety());
		}


		for(int i = 0; i < obsticals.size(); i++)
			if(obsticals.get(i).getOwner() instanceof Ship)
				if(obsticals.get(i).getOwner() != this.getOwner())
					output.add(obsticals.get(i).getOwner());
	
		output.removeAll(alreadyHit);

		return output;
	}

	public void setTeam(int team)
	{
		myteam = team;
	}

	public int getTeam()
	{
		return myteam;
	}

	public Status getStatus()
	{
		return mystatus;
	}


	public Size getsize()
	{
		return mysize;
	}

	public Location getlocation()
	{
		return mylocation;
	}


	public void destroy()
	{
		field.removeObject(this);
		owner.setLaser(null);
	}

	public int getID()
	{
		return myid;
	}

	public void setField(AForceEnv tempfield)
	{
		field = tempfield;
	}

	public void setOwner(Ship owner)
	{
		this.owner = owner;
	}

	public AbstractObject getOwner()
	{
		return owner;
	}

	public static void main(String[] args)
	{
		Printer.noexecute();
	}

	public void update()
	{
		if(owner.getLaser() != this) return;

		direction = Direction.reverse(owner.getDirection());

		setlocation();
		setsize();
		if(real) dodamage();

		boundaries.add(new Boundary(mylocation, 0, 0, Direction.EAST, 0, this));
		boundaries.add(new Boundary(mylocation, 0, 0, Direction.EAST, 0, this));
		boundaries.add(new Boundary(mylocation, 0, 0, Direction.EAST, 0, this));
		boundaries.add(new Boundary(mylocation, 0, 0, Direction.EAST, 0, this));
	}



	public Boundary relaventBoundary(int direction)
	{
		if(direction == Direction.NORTH) return boundaries.get(0);
		if(direction == Direction.SOUTH) return boundaries.get(1);
		if(direction == Direction.WEST) return boundaries.get(2);
		if(direction == Direction.EAST) return boundaries.get(3);

		Printer.err.println("ERROR 519: Direction could not be detected! Returning Null! #Laser.relaventboundary()");
		return null;
	}


	public ArrayList<Boundary> getBoundaries()
	{
		return boundaries;
	}


	public void paint(Graphics g)
	{
		g.setColor(color);
		g.drawRect(mylocation.getx(), mylocation.gety(), mysize.getx(), mysize.gety());
		if(AForce.clicker.getElapsedTime() >= deathTime) destroy();
	}
}